//////////////////////////////////////////////////////////////////////////////////////////////////////
// 项目名   : Container
// 文件名   : TestMap.h
// 作者     : Aiye
// 日期     : 2025/9/4 22:21
// 邮箱     : 2878548868@qq.com
// 摘要     : 介绍map容器
//////////////////////////////////////////////////////////////////////////////////////////////////////
#ifndef CONTAINER_TESTMAP_H
#define CONTAINER_TESTMAP_H
#include <iostream>
#include <map>
#include <string>
#include <vector>

class TestMap
{
public:
    /**
     * @brief 测试构造函数
     */
    static void TestConstructor()
    {
        std::map<int , std::string> map1{}; // 默认构造函数，默认情况下键按照升序排序
        std::map<int , std::string , std::greater<int>> map2{}; // 键按照降序排序
        // map容器的每一个元素都为std::pair
        std::vector<std::pair<int , std::string>> nstrVec{{1,"one"} , {2 , "two"} ,{3 , "three"}};
        std::map map3(nstrVec.begin() , nstrVec.end()); // C++17中编译器会根据构造函数的参数自动推导出模板类型

        auto map4{map3}; // 拷贝构造函数，不共享内存
        auto map5{std::move(map4)}; // 移动构造函数

        decltype(map1) map6{{1,"One"},{2,"Two"},{3,"Three"}}; // 初始化列表构造
        decltype(map1) map7{{1,"One"},{2,"Two"},{3,"Three"},{3,"Four"}}; // 初始化列表构造的时候如果键已有，则会覆盖已有键的值。
    }

    /**
     * @brief 测试赋值函数
     */
    static void TestAssign()
    {
        std::map<int , std::string> map1 = {{1,"One"},{2,"Two"}}; //
        auto map2 = map1; // 拷贝赋值
        auto map3 = std::move(map2); // 移动赋值
        map1 = {{4, "four"}, {5, "five"}}; // 初始化列表构造
        // map没有assign函数
    }

    /**
     * @brief 测试节点容量
     */
    static void TestCapacity()
    {
        std::map<int, std::string> map1 = {{1, "one"}, {2, "two"}, {3, "three"}};
        std::cout << "Size: " << map1.size() << std::endl; // map是基于节点类型的容器和list一样不存在capacity、reverse的概念

        std::cout << "Empty:" << map1.empty(); //
    }

    /**
     * @brief 测试元素访问
     */
    static void TestInterviews()
    {
        std::map<int, std::string> nstrMap = {{1, "one"}, {2, "two"}, {3, "three"}};
        std::cout << nstrMap[1] << std::endl; // 输出one
        nstrMap[4] = "Four"; // 如果不存在该键，则会自动创建并插入

        std::map<std::string , std::string> sstrMap{{"Aiye", "Hello" } , {"Alice"," World"}};
        std:: cout << sstrMap["Aiye"] << " " << sstrMap["Alice"] << std::endl ; // 输出 Hello World

        try
        {
            std::cout << nstrMap.at(2) << std::endl; // 输出two
            std::cout << nstrMap.at(5) << std::endl; // 抛出异常
        }
        catch (const std::out_of_range& e)
        {
            std::cout << "Key not found: " << e.what() << std::endl;
        }
    }

    /**
     * @brief 增加元素
     */
    static void TestAdd()
    {
        std::map<int , std::string> nstrMap{};
        auto bSuccessed = nstrMap.insert({1 , "one"}); // insert插入元素

        auto hint = nstrMap.begin();
        nstrMap.insert(hint , {1 , "one"}); // 提示位置插入
        bSuccessed = nstrMap.emplace(3, "three"); // 内部构造
        nstrMap.emplace_hint(nstrMap.end() , 4 , "four"); // 提示位置构造
        nstrMap[5] = "five"; // 访问下标运算符构造
    }

    /**
     * @brief 测试删除操作
     */
    static void TestDelete()
    {
        std::map<int, std::string> nstrMap{{1, "one"}, {2, "two"}, {3, "three"}, {4, "four"}, {5, "five"}};
        // 通过键删除
        auto nCount = nstrMap.erase(3); // 返回被删除元素的数量
        auto it = nstrMap.find(2); //
        if (it != nstrMap.end())
        {
            nstrMap.erase(it); // 通过迭代器删除元素
        }

        auto first = nstrMap.find(4);
        auto last = nstrMap.end();
        nstrMap.erase(first , last); // 范围删除
        nstrMap.clear(); // 删除所有元素
    }

    /**
     * @brief 查找
     */
    static void TestFind()
    {
        std::map<int, std::string> nstrMap{{1, "one"}, {2, "two"}, {3, "three"}, {4, "four"}, {5, "five"}};

        auto it =nstrMap.find(3); // find查找
        if (it != nstrMap.end())
        {
            std::cout << it->first << "=>" << it->second << std::endl;
        }

        if (nstrMap.count(4))
        {
            std::cout << "Key 4 exists" << std::endl;
        }

        auto low = nstrMap.lower_bound(2); //
        auto upper = nstrMap.upper_bound(4);
        for (auto it = low ; it != upper ; it++)
        {
            std::cout << it->first << "=>" << it->second << std::endl; // 范围查找
        }

        auto range = nstrMap.equal_range(3); // 匹配键的范围
        for (auto it = range.first ; it != range.second ; ++it)
        {
            std::cout << it->first << "=>" << it->second << std::endl; // 范围匹配
        }
    }
    /**
     * @brief 测试修改操作
     */
    static void TestModifaction()
    {
        std::map<int, std::string> nstrMap{{1, "one"}, {2, "two"}, {3, "three"}, {4, "four"}, {5, "five"}};
        nstrMap[1] = "first" ; // 下标访问运算符修改
        nstrMap.at(2) = "second"; // at修改

        auto it = nstrMap.find(3) ;
        if (it != nstrMap.end())
        {
            it->second = "third";
        }
        std::map<int , std::string> otherMap{{10 , "ten"},{20 , "twenty"}};
        nstrMap.swap(otherMap); // 交换两个map
    }

    /**
     * @brief 迭代器
     */
    static void TestIterator()
    {
        std::map<int, std::string> myMap = {
            {1, "one"},
            {2, "two"},
            {3, "three"},
            {4, "four"},
            {5, "five"}
        };

        // 正向迭代
        std::cout << "Forward iteration:" << std::endl;
        for (auto it = myMap.begin(); it != myMap.end(); ++it)
        {
            std::cout << it->first << " => " << it->second << std::endl;
        }

        // 反向迭代
        std::cout << "Reverse iteration:" << std::endl;
        for (auto it = myMap.rbegin(); it != myMap.rend(); ++it)
        {
            std::cout << it->first << " => " << it->second << std::endl;
        }

        // 常量迭代器（防止修改）
        std::cout << "Const iteration:" << std::endl;
        for (auto it = myMap.cbegin(); it != myMap.cend(); ++it)
        {
            // it->second = "new value"; // 错误：不能通过常量迭代器修改值
            std::cout << it->first << " => " << it->second << std::endl;
        }

        // 基于范围的for循环（C++11）
        std::cout << "Range-based for loop:" << std::endl;
        for (const auto& pair : myMap)
        {
            std::cout << pair.first << " => " << pair.second << std::endl;
        }
    }

};
#endif //CONTAINER_TESTMAP_H